package com.framework.admin.service.impl;

import com.framework.admin.model.*;
import com.framework.admin.repository.*;
import com.google.common.collect.Lists;
import com.framework.admin.domain.dto.PassWordEmailDto;
import com.framework.admin.domain.param.SysUserParam;
import com.framework.admin.mapper.UserMapper;
import com.framework.admin.service.IUserService;
import com.framework.admin.vo.SysUserVO;
import com.framework.common.config.SessionUtil;
import com.framework.common.constants.FieldConstant;
import com.framework.common.exception.BusinessException;
import com.framework.common.model.CommonUser;
import com.framework.common.util.BeanUtils;
import com.framework.common.util.RSAEncrypt;
import com.framework.common.util.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserService implements IUserService {
    @Value("${login.privateKey}")
    String privateKey;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SysUserRoleRepository sysUserRoleRepository;
    @Autowired
    private SysUserDeptRepository sysUserDeptRepository;

    @Autowired
    private SysDeptRepository sysDeptRepository;

    @Autowired
    private SysRoleRepository sysRoleRepository;

    @Override
    @Transactional
    public Page<SysUserVO> getUserList(SysUser sysUser, Pageable pageable) {
        List<String> deptIds = userMapper.childDeptIds(sysUser.getDeptId());
        Page<SysUserVO> page = userMapper.findUsers(sysUser, deptIds, pageable);
        String deptNames;
        String roleNames;
        for (SysUserVO user : page.getContent()) {
            List<SysUserDept> userDepts = sysUserDeptRepository.findByUserId(user.getId());
            if (StringUtils.isEmpty(userDepts)) {
                continue;
            }
            List<String> deptIdList = userDepts.stream().map(SysUserDept::getDeptId).collect(Collectors.toList());
            List<String> deptNameList = Lists.newArrayList();
            for (String deptId : deptIdList) {
                SysDept sysDept = sysDeptRepository.findOne(deptId);
                if (sysDept != null) {
                    deptNameList.add(sysDept.getFullName());
                }
            }
            deptNames = StringUtils.join(deptNameList, ",");
            user.setDeptNames(deptNames);
            user.setDeptIds(deptIdList);
            List<SysUserRole> userRoles = sysUserRoleRepository.findByUserId(user.getId());
            if (StringUtils.isEmpty(userRoles)) {
                continue;
            }
            List<String> roleIdList = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
            user.setRoleIds(roleIdList);
            List<String> roleNameList = Lists.newArrayList();
            for (String roleId : user.getRoleIds()) {
                SysRole sysRole = sysRoleRepository.findOne(roleId);
                if (sysRole != null) {
                    roleNameList.add(sysRole.getName());
                }
            }
            roleNames = StringUtils.join(roleNameList, ",");
            user.setRoleNames(roleNames);
        }
        return page;
    }

    @Override
    public List<SysUser> allList(SysUser sysUser) {
        String authCode = SessionUtil.getDefaultDeptCode();
        // 这个地方感觉有问题
        return userMapper.findWorkflowUsers(sysUser, authCode);
    }

    @Override
    public SysUser findThirdPartUser(Map<String, String> param) {
        return userMapper.findThirdPartUser(param);
    }

    @Override
    public void saveInfo(SysUser user) {
        userMapper.saveInfo(user);
    }

    @Override
    public void enable(SysUser user) {
        SysUser param = new SysUser();
        param.setId(user.getId());
        param.setStatus(user.getStatus());
        userMapper.saveInfo(param);
    }

    @Override
    public void changePassword(String id, PassWordEmailDto dto) {
        try {
            SysUser sysUser = userRepository.findOne(id);

            if (StringUtils.isNotBlank(dto.getNewPass()) && StringUtils.isNotBlank(dto.getOldPass())) {
                //密码加密
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                String oldPass = RSAEncrypt.decrypt(dto.getOldPass(), privateKey);
                String password = RSAEncrypt.decrypt(dto.getNewPass(), privateKey);
                if (!passwordEncoder.matches(oldPass, sysUser.getPassword())) {
                    throw new BusinessException("密码错误");
                }

                String enNewPass = passwordEncoder.encode(password);
                sysUser.setPassword(enNewPass);
            }

            if (StringUtils.isNotBlank(dto.getEmail())) {
                sysUser.setEmail(dto.getEmail());
            }
            userRepository.save(sysUser);
        } catch (BusinessException e) {
          throw e;
        } catch (Exception e) {
            throw new BusinessException("密码修改失败");
        }
    }


    @Override
    public SysUser getUserById(String id) {
        return userRepository.findOne(id);
    }

    @Override
    public void save(SysUserParam user) {
        List<String> deptIds = user.getDeptIds();
        // 取第一个作为默认的部门
        if (ObjectUtils.isNotEmpty(deptIds)) {
            user.setDeptId(deptIds.get(0));
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(user, sysUser);
        if (StringUtils.isNotBlank(sysUser.getId())) {
            //前端会传空字符串
            sysUser.setPassword(null);
            userRepository.updateById(sysUser);
        } else {
            //密码加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            //加密
            String defPwd = passwordEncoder.encode(FieldConstant.DEFAULT_PASSWORD);
            sysUser.setPassword(defPwd);
            SysUser dbUser = userRepository.findByAccount(user.getAccount());
            if (dbUser != null) {
                throw new BusinessException("该账号已存在!请勿重复添加。");
            }
            sysUser = userRepository.save(sysUser);
        }
        List<String> userIds = new ArrayList<>();
        userIds.add(user.getId());
        if (ObjectUtils.isNotEmpty(deptIds)) {
            sysUserDeptRepository.deleteByUserIdIn(userIds);
            List<SysUserDept> sysUserDepts = new ArrayList<>();
            for (String it : deptIds) {
                SysUserDept userDept = new SysUserDept();
                userDept.setDeptId(it);
                userDept.setUserId(sysUser.getId());
                sysUserDepts.add(userDept);
            }
            sysUserDeptRepository.saveAll(sysUserDepts);
        }

        List<String> roleIds = user.getRoleIds();
        if (null != roleIds && roleIds.size() > 0) {
            sysUserRoleRepository.deleteByUserIdIn(userIds);
            List<SysUserRole> sysUserRoles = new ArrayList<>();
            for (String roleId : roleIds) {
                SysUserRole userRole = new SysUserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(sysUser.getId());
                sysUserRoles.add(userRole);
            }
            sysUserRoleRepository.saveAll(sysUserRoles);
        }
    }

    @Override
    public void delete(List<String> ids) {
        String[] arr = new String[ids.size()];
        userRepository.deleteById(ids.toArray(arr));
        sysUserRoleRepository.deleteByUserIdIn(ids);
    }

    @Override
    public void resetPassword(String id) {
        //密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //加密
        String defPwd = passwordEncoder.encode(FieldConstant.DEFAULT_PASSWORD);
        SysUser user = getUserById(id);
        user.setPassword(defPwd);
        userRepository.save(user);

        CommonUser currUser = SessionUtil.getUser();
        if (id.equals(currUser.getId())) {
            SessionUtil.clear();
        }
    }
}
